package com.matrix.order.infrastructure.payment.impl;

import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.matrix.common.constant.RocketMQConstants;
import com.matrix.common.exception.BusinessException;
import com.matrix.order.config.WechatPayProperties;
import com.matrix.order.infrastructure.payment.PaymentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;

/**
 * @author 有点甜
 * @since 2025/8/2
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WechatPaymentServiceImpl implements PaymentService {

    private final WxPayService wxPayService;
    private final WechatPayProperties properties;
    private final RocketMQTemplate rocketMQTemplate;

    @Override
    public String createNativePayment(String tradeNo, BigDecimal amount, String description) {
        try {
            WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
            request.setAppid(properties.getAppId());
            request.setMchid(properties.getMchId());
            request.setOutTradeNo(tradeNo);
            request.setDescription(description);
            request.setNotifyUrl(properties.getNotifyUrl());

            WxPayUnifiedOrderV3Request.Amount wxAmount = new WxPayUnifiedOrderV3Request.Amount();
            int totalFee = amount.multiply(new BigDecimal("100")).intValue();
            wxAmount.setTotal(totalFee);
            wxAmount.setCurrency("CNY");
            request.setAmount(wxAmount);

            WxPayUnifiedOrderV3Result result = wxPayService.createOrderV3(TradeTypeEnum.NATIVE, request);

            int delayLevel = 16;
            org.springframework.messaging.Message<String> message = MessageBuilder.withPayload(tradeNo).build();
            rocketMQTemplate.syncSend(RocketMQConstants.ORDER_PAY_TIMEOUT_TOPIC, message, 3000, delayLevel);
            log.info("已为订单 {} 发送延迟检查消息,延迟等级: {}", tradeNo, delayLevel);

            return result.getCodeUrl();
        } catch (Exception e) {
            log.error("微信支付统一下单失败 for tradeNo {}", tradeNo, e);
            throw new BusinessException("创建支付订单失败,请稍后再试" + e);
        }
    }

    @Override
    public void refund(String tradeNo, BigDecimal amount, String reason) {
        try {
            WxPayRefundV3Request request = new WxPayRefundV3Request();
            request.setOutTradeNo(tradeNo);
            request.setOutRefundNo(tradeNo + "-REFUND");
            request.setReason(reason);

            WxPayRefundV3Request.Amount wxAmount = new WxPayRefundV3Request.Amount();
            int refundFee = amount.multiply(new BigDecimal("100")).intValue();
            wxAmount.setRefund(refundFee);
            wxAmount.setTotal(refundFee);
            wxAmount.setCurrency("CNY");
            request.setAmount(wxAmount);

            log.info("发起退款,订单号: {}, 退款原因: {}", tradeNo, reason);
            WxPayRefundV3Result result = wxPayService.refundV3(request);

            String status = result.getStatus();
            if ("SUCCESS".equals(status)) {
                log.info("订单 {} 退款申请成功,等待银行处理。", tradeNo);
            } else if ("PROCESSING".equals(status)) {
                log.info("订单 {} 退款处理中,请稍后查询结果。", tradeNo);
            } else {
                log.error("订单 {} 退款异常,状态: {}", tradeNo, status);
                throw new BusinessException("退款失败,请联系管理员处理");
            }

        } catch (Exception e) {
            log.error("微信支付退款失败", e);
            throw new BusinessException("发起退款失败,请稍后再试" + e);
        }
    }

    @Override
    public void closeOrder(String tradeNo) {
        if (!StringUtils.hasText(tradeNo)) {
            return;
        }
        try {
            wxPayService.closeOrderV3(tradeNo);
            log.info("微信支付订单 {} 已成功关闭。", tradeNo);
        } catch (WxPayException e) {
            if ("ORDER_PAID".equals(e.getErrCode()) || "ORDER_CLOSED".equals(e.getErrCode())) {
                log.info("关闭微信支付订单 {} 失败,原因: {}。此为正常业务场景。", tradeNo, e.getErrCodeDes());
            } else {
                log.error("关闭微信支付订单 {} 时发生未知错误: {}", tradeNo, e.getMessage());
            }
        } catch (Exception e) {
            log.error("关闭微信支付订单 {} 时发生系统异常", tradeNo, e);
        }
    }
}
